/**
 * 
 */
package com.hanhai.zrb.api.biz.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.hanhai.common.bizInterface.ChangeNotify;
import com.hanhai.common.cache.Cache;
import com.hanhai.zrb.api.biz.dao.mybatis.UserStatisticDetailMapper;
import com.hanhai.zrb.api.biz.service.BizMonitorService;
import com.hanhai.zrb.api.biz.service.CommonCounterService;
import com.hanhai.zrb.api.biz.service.FundService;
import com.hanhai.zrb.api.biz.service.IntentionService;
import com.hanhai.zrb.api.biz.service.MessageSendService;
import com.hanhai.zrb.api.biz.service.ProjectService;
import com.hanhai.zrb.api.biz.service.SysDictionaryService;
import com.hanhai.zrb.api.biz.service.UserService;
import com.hanhai.zrb.api.biz.service.UserStatisticDetailService;
import com.hanhai.zrb.api.mongodb.SpringContextUtil;
import com.hanhai.zrb.model.common.CommonCounter;
import com.hanhai.zrb.model.common.CommonCounterKey;
import com.hanhai.zrb.model.common.SysDictionary;
import com.hanhai.zrb.model.common.enums.ProvinceEnum;
import com.hanhai.zrb.model.common.enums.StatusEnums;
import com.hanhai.zrb.model.fund.Fund;
import com.hanhai.zrb.model.intention.Intention;
import com.hanhai.zrb.model.project.Project;
import com.hanhai.zrb.model.user.User;
import com.hanhai.zrb.model.user.UserStatisticDetail;
import com.hanhai.zrb.model.user.UserStatisticDetail.Type;
import com.hanhai.zrb.model.user.dto.UserStatisticDetailDto;
import com.hanhai.zrb.model.usercenter.CommonStatistic;
import com.hanhai.zrb.model.usercenter.IntentionStatistic;

/**
 * @author leiruiqi
 *
 */
@Service("userStatisticDetailService")
public class UserStatisticDetailServiceImpl implements UserStatisticDetailService,ChangeNotify{

	private final Logger logger = LoggerFactory
			.getLogger(UserStatisticDetailServiceImpl.class);
	
	@Resource
	private UserStatisticDetailMapper userStatisticDetailMapper;
	
	@Resource
	private CommonCounterService commonCounterService;
	
	@Resource
	private FundService fundService;
	
	@Autowired
	private ProjectService projectService;
	
	@Resource
	private IntentionService intentionService;
	
	@Resource
	private UserService userService;
	
	@Resource
	private SysDictionaryService sysDictionaryService;
	
	@Resource
	private Cache defaultCache;
	
	@Resource
	private MessageSendService messageSendService;
	
	//@Resource
	//private AsyncBiz asyncBiz;
	@PostConstruct
	@Override
	public void addListener() {
		//ChangeNotifyUtil.addListener(InformationService.notifySubject_del_information, this);		
	}

	@Override
	public void change(String subject,Object bizNo) {
		/*if(StringUtils.equals(subject, InformationService.notifySubject_del_information)){
			Long informationId = (Long)bizNo;
			removeAllUserCollectionByType(informationId,UserCollection.Type.information);
		}*/
	}
	
	public void removeAllUserCollectionByType(Long informationId,UserStatisticDetail.Type type){
		
		int deleteCount = userStatisticDetailMapper.deleteByInfoId(informationId,type.getCode());
		
		CommonCounterKey commonCounterKey = getCommonCounterKey(informationId,type);
		CommonCounter commonCounter = new CommonCounter();
		commonCounter.setMainKey(commonCounterKey.getMainKey());
		commonCounter.setSecondaryKey(commonCounterKey.getSecondaryKey());
		commonCounter.setValue(0L);
		commonCounterService.update(commonCounter);
	}
	
	@Override
	public boolean doCollection(UserStatisticDetail userStatisticDetail) {
		boolean addSucceed = save(userStatisticDetail);
		if(addSucceed){
			Long destId = userStatisticDetail.getDestId();
			Integer type = userStatisticDetail.getType();
			Long userId=userStatisticDetail.getUserId();
			CommonCounterKey commonCounterKey = getCommonCounterKey(destId,type);
			boolean addcountResult = commonCounterService.addOneByLock(commonCounterKey);
			if(addcountResult == false){
				logger.error("commonCounterService.addOneByLock false");
			}
			BizMonitorService bizMonitor = getBizMonitorService();
			bizMonitor.collection(userStatisticDetail);
			return true;
		}
		return false;
	}

	

	private boolean save(UserStatisticDetail userStatisticDetail){
		if(userStatisticDetail.getCreateTime() == null){
			userStatisticDetail.setCreateTime(new Date());
		}
		try {
			userStatisticDetailMapper.insert(userStatisticDetail);
			return true;
		} catch (Exception e) {
			return false;
		}
	}
	
	private boolean delete(UserStatisticDetail userStatisticDetail){
		return 1==userStatisticDetailMapper.deleteByUserIdAndInfoIdAndType(userStatisticDetail.getUserId(),userStatisticDetail.getDestId(),userStatisticDetail.getType());
	}
	
	private CommonCounterKey getCommonCounterKey(Long collectionId,UserStatisticDetail.Type type ){
		CommonCounterKey keys = new CommonCounterKey();
		keys.setMainKey(type.getCountKey());
		keys.setSecondaryKey(String.valueOf(collectionId));
		return keys;
	}
	
	private CommonCounterKey getCommonCounterKey(Long collectionId,int typeCode){
		UserStatisticDetail.Type type = UserStatisticDetail.Type.getValue(typeCode);
		if(type==null){
			throw new RuntimeException();
		}
		return this.getCommonCounterKey(collectionId, type);
	}
	
	private List<CommonCounterKey> getCommonCounterKeyList(List<Long> informationIdList,UserStatisticDetail.Type type){
		List<CommonCounterKey> list = new ArrayList<CommonCounterKey>();
		for(Long id:informationIdList){
			CommonCounterKey keys = new CommonCounterKey();
			keys.setMainKey(type.getCountKey());
			keys.setSecondaryKey(String.valueOf(id));
			list.add(keys);
		}
		
		return list;
	}

	@Override
	public boolean doCancelCollection(UserStatisticDetail userStatisticDetail) {
		if(delete(userStatisticDetail)){
			CommonCounterKey commonCounterKey = getCommonCounterKey(userStatisticDetail.getDestId(),userStatisticDetail.getType());
			boolean subcountResult = commonCounterService.subOneByLock(commonCounterKey);
			if(subcountResult == false){
				logger.error("commonCounterService.subOneByLock false");
			}
			return true;
		}
		return false;
	}

	
	@Override
	public List<UserStatisticDetail> queryByCondition(Date createTime,boolean forward,Long userId,Integer type,Integer limit){
		UserStatisticDetailDto userStatisticDetailDto = new UserStatisticDetailDto();
		userStatisticDetailDto.setUserId(userId);
		userStatisticDetailDto.setType(type);
		if(forward){
			userStatisticDetailDto.setStartTime(createTime);
		}else{
			userStatisticDetailDto.setEndTime(createTime);
		}
		userStatisticDetailDto.setPageNum(1);
		userStatisticDetailDto.setPageSize(limit);
		
		PageInfo pageInfo = queryPageByCondition(userStatisticDetailDto);
		return pageInfo.getList();
	}
	
	@Override
	public Boolean isCollected(Long uid,Long id,Integer type){
		UserStatisticDetailDto dto = new UserStatisticDetailDto();
		dto.setUserId(uid);
		dto.setDestId(id);
		dto.setType(type);
		List<UserStatisticDetail> list =  userStatisticDetailMapper.queryByCondition(dto);
		return CollectionUtils.isEmpty(list)?false:true;
	}
	
	@Override
	public PageInfo queryPageByCondition(UserStatisticDetailDto userStatisticDetailDto){
		PageHelper.startPage(userStatisticDetailDto.getPageNum(), userStatisticDetailDto.getPageSize(), true);
		List<UserStatisticDetail> page = userStatisticDetailMapper.queryByCondition(userStatisticDetailDto);
		PageInfo pageInfo = new PageInfo(page);
		return pageInfo;
	}


	@Override
	public Long getCollectionCounter(Long bizId, Type type) {
		CommonCounterKey  key = getCommonCounterKey(bizId,type);
		return commonCounterService.getCurrentCountByKey(key);
	
	}

	@Override
	public List<UserStatisticDetail> queryByUserIdAndType(Long userId, Type type) {
		Integer typeValue = null;
		if(type != null ){
			typeValue = type.getCode();
		}
		return this.userStatisticDetailMapper.queryByUserId(userId,typeValue);
	}

	@Override
	public Map<Long, Long> getCollectionCounterMap(List<Long> idList, Type type) {
		Map<Long,Long> map = new HashMap<Long,Long>();
		if(CollectionUtils.isEmpty(idList)){
			return map;
		}
		List<CommonCounterKey> keyList = getCommonCounterKeyList(idList,type);
		List<CommonCounter> commonCounterlist = commonCounterService.getListByKeyList(keyList);
		
		
		for(CommonCounter commonCounter:commonCounterlist){
			map.put(Long.valueOf(commonCounter.getSecondaryKey()), commonCounter.getValue());
		}
		return map;
	}

	@Override
	public List<CommonStatistic> getUserCollectionProject(Long userId,Date maxCreateTime,Integer limit){
		List<UserStatisticDetail> collectionList = this.queryByCondition(maxCreateTime, false, userId, UserStatisticDetail.Type.pro_col.getCode(), limit);
		List<CommonStatistic> returnList = this.buildProjectInfoVoList(collectionList);
		return returnList;
	}
	
	@Override
	public List<CommonStatistic> getUserCollectionFund(Long userId,Date maxCreateTime,Integer limit){
		List<UserStatisticDetail> collectionList = this.queryByCondition(maxCreateTime, false, userId, UserStatisticDetail.Type.fund_col.getCode(), limit);
		List<CommonStatistic> returnList = this.buildFundsList(collectionList);
		return returnList;
	}
	
	@Override
	public List<IntentionStatistic> getUserCollectionIntention(Long userId,Date maxCreateTime,Integer limit){
		List<UserStatisticDetail> collectionList = this.queryByCondition(maxCreateTime, false, userId, UserStatisticDetail.Type.inten_col.getCode(), limit);
		List<IntentionStatistic> returnList = this.buildIntentionsList(collectionList);
		return returnList;
	}
	
	public PageInfo getUserCollectionProjectPage(UserStatisticDetailDto dto){
		
		PageInfo pageInfo = this.queryPageByCondition(dto);
		List<UserStatisticDetail> collectionList = pageInfo.getList();
		List<CommonStatistic> returnList = this.buildProjectInfoVoList(collectionList);
		pageInfo.setList(returnList);
		return pageInfo;
	}
	
	private List<CommonStatistic> buildProjectInfoVoList(List<UserStatisticDetail> collectionList){
		List<CommonStatistic> returnList = new ArrayList<CommonStatistic>();
		if(CollectionUtils.isEmpty(collectionList)){
			return returnList;
		}
		List<Long> idList = new ArrayList<Long>();
		for(UserStatisticDetail userStatisticDetail:collectionList){
			idList.add(userStatisticDetail.getDestId());
		}
		
		Map<Long,Project> map = projectService.queryMapByIdList(idList);
		if(!map.isEmpty()){
			for(UserStatisticDetail userStatisticDetail:collectionList){
				if(map.containsKey(userStatisticDetail.getDestId())){
					Project pro = map.get(userStatisticDetail.getDestId());
					if(pro.getProjectStatus().intValue()==StatusEnums.RELEASE.getCode().intValue()){
						CommonStatistic statistic = new CommonStatistic();
						statistic.setCreateTime(userStatisticDetail.getCreateTime());
						statistic.setProvince(ProvinceEnum.getProvinceName(Integer.valueOf(pro.getProvincePostcode())));
						statistic.setTitle(pro.getProjectName());
						statistic.setTotal((null==pro.getTotal()?0:pro.getTotal().setScale(2, BigDecimal.ROUND_HALF_UP)).toString());
						statistic.setId(pro.getId());
						returnList.add(statistic);
					}
				}
			}
		}
		return returnList;
	}
	
	
	private List<CommonStatistic> buildFundsList(List<UserStatisticDetail> collectionList){
		List<CommonStatistic> returnList = new ArrayList<CommonStatistic>();
		if(CollectionUtils.isEmpty(collectionList)){
			return returnList;
		}
		List<Long> idList = new ArrayList<Long>();
		for(UserStatisticDetail userStatisticDetail:collectionList){
			idList.add(userStatisticDetail.getDestId());
		}
		
		Map<Long,Fund> map = fundService.queryByIdList(idList);
		if(!map.isEmpty()){
			for(UserStatisticDetail userStatisticDetail:collectionList){
				if(map.containsKey(userStatisticDetail.getDestId())){
					Fund fund = map.get(userStatisticDetail.getDestId());
					if(fund.getState().equals(StatusEnums.RELEASE.getCode())){
						CommonStatistic statistic = new CommonStatistic();
						statistic.setCreateTime(userStatisticDetail.getCreateTime());
						if(StringUtils.isNoneBlank(fund.getDestination())){
							String[] destIds = fund.getDestination().split("#");
							String areas = "";
							for(String id:destIds){
								if(!"".equals(areas)){
									areas=areas+"/"+ProvinceEnum.getProvinceName(Integer.valueOf(id));
								}else{
									areas=ProvinceEnum.getProvinceName(Integer.valueOf(id));
								}
							}
							statistic.setProvince(areas);
						}
						
						statistic.setTitle(fund.getTitlesVal());
						statistic.setTotal((null==fund.getTotal()?0:new BigDecimal(fund.getTotal()).setScale(2, BigDecimal.ROUND_HALF_UP)).toString());
						statistic.setId(fund.getId());
						returnList.add(statistic);
					}
				}
			}
		}
		return returnList;
	}
	
	
	private List<IntentionStatistic> buildIntentionsList(List<UserStatisticDetail> collectionList){
		List<IntentionStatistic> returnList = new ArrayList<IntentionStatistic>();
		if(CollectionUtils.isEmpty(collectionList)){
			return returnList;
		}
		List<Long> idList = new ArrayList<Long>();
		for(UserStatisticDetail userStatisticDetail:collectionList){
			idList.add(userStatisticDetail.getDestId());
		}
		
		Map<Long,Intention> map = intentionService.getIntentionMap(idList);
		if(!map.isEmpty()){
			for(UserStatisticDetail userStatisticDetail:collectionList){
				if(map.containsKey(userStatisticDetail.getDestId())){
					IntentionStatistic statistic = new IntentionStatistic();
					statistic.setCreateTime(userStatisticDetail.getCreateTime());
					Intention intention = map.get(userStatisticDetail.getDestId());
					statistic.setTitle(intention.getIntro());
					statistic.setId(intention.getId());
					statistic.setType(intention.getType());
					User user = userService.findById(intention.getUserId());
					SysDictionary sysDictionary=sysDictionaryService.getByCodeFromLocalCache(intention.getType().toString());
					statistic.setUserName(user.getRealname());
					statistic.setTypeName(sysDictionary.getItemName());
					
					CommonCounterKey commonCounterKey = new CommonCounterKey();
					commonCounterKey.setMainKey(UserStatisticDetail.Type.inten_col.getCountKey());
					commonCounterKey.setSecondaryKey(intention.getId().toString());
					statistic.setCollectNum(commonCounterService.getCurrentCountByKey(commonCounterKey));
					
					commonCounterKey.setMainKey(UserStatisticDetail.Type.inten_message.getCountKey());
					statistic.setMessageNum(commonCounterService.getCurrentCountByKey(commonCounterKey));
					returnList.add(statistic);
				}
			}
		}
		
		return returnList;
	}

	@Override
	public int getCountByType(Integer type,Long userId) {
		return userStatisticDetailMapper.getCountByType(type,userId);
	}

	@Override
	public PageInfo getUserCollectionIntentionPage(UserStatisticDetailDto dto) {
		PageInfo pageInfo = this.queryPageByCondition(dto);
		List<UserStatisticDetail> collectionList = pageInfo.getList();
		List<IntentionStatistic> returnList = this.buildIntentionsList(collectionList);
		pageInfo.setList(returnList);
		return pageInfo;
	}

	@Override
	public PageInfo getUserCollectionFundPage(UserStatisticDetailDto dto) {
		PageInfo pageInfo = this.queryPageByCondition(dto);
		List<UserStatisticDetail> collectionList = pageInfo.getList();
		List<CommonStatistic> returnList = this.buildFundsList(collectionList);
		pageInfo.setList(returnList);
		return pageInfo;
	}

	private BizMonitorService getBizMonitorService() throws BeansException { 
        return (BizMonitorService) SpringContextUtil.getBean("bizMonitorService"); 
	} 
}
